package kla;

import static robocode.util.Utils.normalRelativeAngleDegrees;
import robocode.HitRobotEvent;
import robocode.HitWallEvent;
import robocode.Robot;
import robocode.ScannedRobotEvent;
import java.awt.Color;

/**
 * Tankadin - a robot by Ardell Klemme.
 * 
 * @author Ardell Klemme
 */
public class Tankadin extends Robot {

  private String smiteMe = null;
  private boolean lockedOn = false, moving = false;
  private double targetBearing;

  /**
   * Attempts to lock onto an enemy tank and track it.  If hit or fired upon, go to random corner. 
   */
  public void run() {
    
    // Set colors
    setBulletColor(Color.yellow);
    setGunColor(Color.yellow);
    setRadarColor(Color.white);
    setBodyColor(Color.white);
    setScanColor(Color.white);

    // free up all three components
    setAdjustGunForRobotTurn(true);
    
    // initial search for target
    turnGunRight(360);
    
    while (true) {
      turnGunLeft(360);
    }
  }

  /**
   * Aims the Robot's gun at the target robot being tracked by the onScannedRobot method.
   */
  public void aimGun() {

    double gunAngle = getHeading() - getGunHeading();

    // get angle to target, and normalize to reduce "spinning effect"
    double targetAngle = normalRelativeAngleDegrees((this.targetBearing + gunAngle));

    turnGunRight(targetAngle);
  }

  /**
   * onScannedRobot: Fires at any robots it finds with a power that is based on distance from 
   * target.
   * 
   * @param e contains information about the enemy robot, e.g. its location
   */
  public void onScannedRobot(ScannedRobotEvent e) {

    if (!lockedOn) {
      this.smiteMe = e.getName();
      lockedOn = true;
    }
    
    if (moving) {
      fire(getPowerLevel(e.getDistance()));
      scan();
    } 
    else {
      
      // return bearing information for our target
      if (this.smiteMe.equals(e.getName())) {
        this.targetBearing = e.getBearing();
      }
      
      aimGun();
      
      fire(getPowerLevel(e.getDistance()));
      scan();
    }
  }
  
  /**
   * Calculates appropriate fire-power per distance.
   * 
   * @param distance the distance to target
   * @return appropriate fire-power level
   */
  public double getPowerLevel(double distance) {
    return (Math.min(400 / distance, 3));
  }
   
  /**
   * onHitWall: Go to random corner.
   * 
   * @param e Event containing information about the wall we just hit.
   */
  public void onHitWall(HitWallEvent e) {
    randomCorner();
  }

  /**
   * Moves Robot to (x, y) coordinate.
   * 
   * @param goalY Y coordinate of target destination
   * @param goalX X coordinate of target destination
   */
  public void goTo(double goalX, double goalY) {

    double yDistance = (goalY - getY());
    double xDistance = (goalX - getX());
    double distanceToGo = 0.0;
    double angleToGoalLeft = (Math.atan2((yDistance), (xDistance)) * (180 / Math.PI));
    // turn shortest distance to goal
    angleToGoalLeft = (getHeading() - 90 + angleToGoalLeft);

    if (angleToGoalLeft <= 180) {
      turnLeft(angleToGoalLeft);
    }
    else {
      turnRight(360 - angleToGoalLeft);
    }
    
    distanceToGo = (Math.sqrt((Math.pow(yDistance, 2) + Math.pow(xDistance, 2))));
    //going to destination, open ability to fire if robot scanned
    moving = true;
    ahead(distanceToGo);
    //arrived, resume tracking behavior
    moving = false;
  }
  
  /**
   * onHitRobot:  Change target to new enemy, then fire upon it and go to random corner.
   * 
   * @param e Event contains information about the robot we hit.
   */
  public void onHitRobot(HitRobotEvent e) {
    
    // Change target to new enemy
    smiteMe = e.getName();
    // Bring guns to bear on new target
    turnGunRight(normalRelativeAngleDegrees(e.getBearing() + (getHeading() - getRadarHeading())));
    fire(3);
    randomCorner();
  }
  
  /**
   * Moves Robot to random corner.
   */
  public void randomCorner() {
    
    double whereTo = 0.0;
    whereTo = Math.random() * 4;
    
    if (whereTo > 1) {
      
      if (whereTo > 2) {
        
        if (whereTo > 3) {
          //go to lower left
          goTo(25, 25);
        }
        else { // 2<X<=3
          //go to upper left
          goTo(25, getBattleFieldHeight() - 25);
        }
        
      }
      else { // 1<X<=2
        //go to lower right
        goTo(getBattleFieldWidth() - 25, 25);
      } 
    }
    else { // X<=1
      //go to upper right 
      goTo(getBattleFieldWidth() - 25, getBattleFieldHeight() - 25);
    }
  } //close randomCorner
}
